package com.vst.orm.dao.hibernate.original;

import java.io.Serializable;
import java.util.List;

import org.hibernate.NonUniqueResultException;

import com.vst.orm.dao.BaseDAODispatcher;
import com.vst.orm.dao.DAODispatcherException;
import com.vst.orm.search.ExampleOptions;
import com.vst.orm.search.Filter;
import com.vst.orm.search.ISearch;
import com.vst.orm.search.SearchResult;

public class DAODispatcher extends BaseDAODispatcher implements GeneralDAO {
	protected GeneralDAO generalDAO;

	public void setGeneralDAO(GeneralDAO generalDAO) {
		this.generalDAO = generalDAO;
	}

	public void create(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				((GenericDAO) specificDAO).create(object);
			} else {
				callMethod(specificDAO, "create", new Object[] { object });
			}
		} else {
			this.generalDAO.create(object);
		}
	}

	public boolean createOrUpdate(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).createOrUpdate(object);
			}
			return ((Boolean) callMethod(specificDAO, "createOrUpdate", new Object[] { object })).booleanValue();
		}
		return this.generalDAO.createOrUpdate(object);
	}

	public boolean deleteById(Class<?> klass, Serializable id) {
		Object specificDAO = getSpecificDAO(klass.getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).deleteById(id);
			}
			return ((Boolean) callMethod(specificDAO, "deleteById", new Object[] { id })).booleanValue();
		}
		return this.generalDAO.deleteById(klass, id);
	}

	public boolean deleteEntity(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).deleteEntity(object);
			}
			return ((Boolean) callMethod(specificDAO, "deleteEntity", new Object[] { object })).booleanValue();
		}
		return this.generalDAO.deleteEntity(object);
	}

	public <T> T fetch(Class<T> klass, Serializable id) {
		Object specificDAO = getSpecificDAO(klass.getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return (T) ((GenericDAO) specificDAO).fetch(id);
			}
			return (T) callMethod(specificDAO, "fetch", new Object[] { id });
		}
		return (T) this.generalDAO.fetch(klass, id);
	}

	public <T> List<T> fetchAll(Class<T> klass) {
		Object specificDAO = getSpecificDAO(klass.getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).fetchAll();
			}
			return (List) callMethod(specificDAO, "fetchAll", new Object[0]);
		}
		return this.generalDAO.fetchAll(klass);
	}

	/**
	 * @deprecated
	 */
	public void flush() {
		throw new DAODispatcherException(
				"The flush() method cannot be used with DAODispatcher because it could does not include a Class type to dispatch to. Use flush(Class<?>).");
	}

	public void flush(Class<?> klass) {
		Object specificDAO = getSpecificDAO(klass.getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				((GenericDAO) specificDAO).flush();
			} else {
				callMethod(specificDAO, "flush", new Object[0]);
			}
		} else {
			this.generalDAO.flush();
		}
	}

	public boolean isConnected(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).isConnected(object);
			}
			return ((Boolean) callMethod(specificDAO, "isConnected", new Object[] { object })).booleanValue();
		}
		return this.generalDAO.isConnected(object);
	}

	public void refresh(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				((GenericDAO) specificDAO).refresh(object);
			} else {
				callMethod(specificDAO, "refresh", new Object[] { object });
			}
		} else {
			this.generalDAO.refresh(object);
		}
	}

	public List search(ISearch search) {
		Object specificDAO = getSpecificDAO(search.getSearchClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).searchGeneric(search);
			}
			try {
				return (List) callMethod(specificDAO, "searchGeneric", new Object[] { search });
			} catch (DAODispatcherException ex) {
				if ((ex.getCause() instanceof NoSuchMethodException)) {
					return (List) callMethod(specificDAO, "search", new Object[] { search });
				}
				throw ex;
			}
		}
		return this.generalDAO.search(search);
	}

	public SearchResult searchAndCount(ISearch search) {
		Object specificDAO = getSpecificDAO(search.getSearchClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).searchAndCount(search);
			}
			return (SearchResult) callMethod(specificDAO, "searchAndCount", new Object[] { search });
		}
		return this.generalDAO.searchAndCount(search);
	}

	public int count(ISearch search) {
		Object specificDAO = getSpecificDAO(search.getSearchClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).count(search);
			}
			return ((Integer) callMethod(specificDAO, "count", new Object[] { search })).intValue();
		}
		return this.generalDAO.count(search);
	}

	public Object searchUnique(ISearch search) throws NonUniqueResultException {
		Object specificDAO = getSpecificDAO(search.getSearchClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).searchUnique(search);
			}
			return callMethod(specificDAO, "searchUnique", new Object[] { search });
		}
		return this.generalDAO.searchUnique(search);
	}

	public void update(Object object) {
		Object specificDAO = getSpecificDAO(object.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				((GenericDAO) specificDAO).update(object);
			} else {
				callMethod(specificDAO, "update", new Object[] { object });
			}
		} else {
			this.generalDAO.update(object);
		}
	}

	public Filter getFilterFromExample(Object example) {
		Object specificDAO = getSpecificDAO(example.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).getFilterFromExample(example);
			}
			return (Filter) callMethod(specificDAO, "getFilterFromExample", new Object[] { example });
		}
		return this.generalDAO.getFilterFromExample(example);
	}

	public Filter getFilterFromExample(Object example, ExampleOptions options) {
		Object specificDAO = getSpecificDAO(example.getClass().getName());
		if (specificDAO != null) {
			if ((specificDAO instanceof GenericDAO)) {
				return ((GenericDAO) specificDAO).getFilterFromExample(example, options);
			}
			return (Filter) callMethod(specificDAO, "getFilterFromExample", new Object[] { example, options });
		}
		return this.generalDAO.getFilterFromExample(example, options);
	}
}
